class Observer {
  constructor({data}) {
    this.data = data
  }
  init(onDataChange){
    const deepObjs = this.getDeepObjs(this.data)
    console.log(deepObjs)
    deepObjs.forEach(obj => Observer.defineObj({data:obj.data, rootPath: obj.path}, onDataChange))
  }
  getDeepObjs(data, rootPath = '') {
    let objs = []
    if (typeof data === 'object') {
      // Observer.defineObj(data, rootPath, this.onDataChange)
      objs.push({data, path: rootPath})
      Object.entries(data).forEach(([key, value]) => {
        const path = rootPath ? `${rootPath}.${key}` : key
        objs.push(...this.getDeepObjs(value, path))
      })
    }
    return objs
  }
  static defineObj({data, rootPath}, onDataChange) {
    if(Array.isArray(data)) Array.observe(data, (changes)=>{console.log(changes)})
    Object.entries(data).forEach(([key, val]) => {
      let value = val
      Object.defineProperty(data, key, {
        set: val => {
          const path = rootPath ? `${rootPath}.${key}` : key
          console.log(path, val)
          onDataChange(path, val)
          value = val
          return value
        },
        get: () => value,
        enumerable: true
      })
      // 初始先执行一次onDataChange操作
      const path = rootPath ? `${rootPath}.${key}` : key
      onDataChange(path, val)
    })
  }
}

function observe({data, onDataChange}) {
  const o = new Observer({data})
  o.init(onDataChange)
  return o.data
}